﻿using System;
using System.Collections.Generic;
using System.Collections;

namespace SharpTag.ID3
{
    /// <summary>
    /// Concrete implementation of the <see cref="IFrameHeader"/> interface.
    /// </summary>
    public class ID3V2TagFrameHeader : IFrameHeader
    {
        /// <summary>
        /// Class constructor.
        /// </summary>
        public ID3V2TagFrameHeader() { IsDirty = false; }

        /// <summary>
        /// Class constructor.
        /// </summary>
        /// <param name="headerBytes">A byte array containing the raw header bytes of the Tag.</param>
        public ID3V2TagFrameHeader(byte[] headerBytes)
        {
            var frameIDBytes = new char[4];
            var sizeBytes = new byte[4];
            var flagBytes = new byte[2];

            Array.Copy(headerBytes, 0, frameIDBytes, 0, 4);
            Array.Copy(headerBytes, 4, sizeBytes, 0, 4);
            Array.Copy(headerBytes, 8, flagBytes, 0, 2);
            Name = new string(frameIDBytes);
            Size = sizeBytes.CalculateSize();
            ParseFlags(flagBytes);
        }

        /// <summary>
        /// Gets the Name of the Frame.
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// Gets the Size of the Frame.
        /// </summary>
        public long Size { get; private set; }

        /// <summary>
        /// Gets the a list of the <see cref="FrameHeaderFlag"/> objects in the Frame.
        /// </summary>
        public List<FrameHeaderFlag> Flags { get; private set; }

        //TDOD: Need to add flag modification methods.

        /// <summary>
        /// Gets whether or not the Header has been modified.
        /// </summary>
        public bool IsDirty { get; private set; }

        /// <summary>
        /// Converts the Frame Header data into a byte array to be written out to the physical file.
        /// </summary>
        /// <returns></returns>
        public byte[] PrepareBytes()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Helper method that parses the header flag data.
        /// </summary>
        /// <param name="flagBytes">A byte array containing the raw header flag data.</param>
        private void ParseFlags(byte[] flagBytes)
        {
            BitArray flags = new BitArray(flagBytes);

            for (int i = 0; i < flags.Length; i++)
            {
                if (flags[i])
                {
                    switch (i)
                    {
                        case 1:
                            Flags.Add(FrameHeaderFlag.TagAlterPreservation);
                            break;
                        case 2:
                            Flags.Add(FrameHeaderFlag.FileAlterPreservation);
                            break;
                        case 3:
                            Flags.Add(FrameHeaderFlag.ReadOnly);
                            break;
                        case 9:
                            Flags.Add(FrameHeaderFlag.GroupingIdentity);
                            break;
                        case 12:
                            Flags.Add(FrameHeaderFlag.Compression);
                            break;
                        case 13:
                            Flags.Add(FrameHeaderFlag.Encryption);
                            break;
                        case 14:
                            Flags.Add(FrameHeaderFlag.Unsynchronisation);
                            break;
                        case 15:
                            Flags.Add(FrameHeaderFlag.DataLengthIndicator);
                            break;
                    }
                }
            }
        }
    }
}
